﻿#region Imports
using System;
using System.Drawing;
using System.Windows.Forms;
using CommonUtilities.Extensions;
using CommonUtilities.Util;
#endregion

namespace CommonUtilities.Controls
{
    /// <summary>
    /// CommonUtilities TextBox
    /// (inherited from System.Windows.Forms.TextBox)
    /// </summary>
    public class CUtil_TextBox : TextBox
    {
        #region Declarations
        /// <summary>
        /// Occurs when the mouse pointer enters the control
        /// </summary>
        public new event EventHandler MouseEnter;

        /// <summary>
        /// Occurs when the mouse pointer leaves the control
        /// </summary>
        public new event EventHandler MouseLeave;

        /// <summary>
        /// Occurs when the control receives focus
        /// </summary>
        public new event EventHandler GotFocus;

        /// <summary>
        /// Occurs when the <code>System.Windows.Forms.Control.Text</code> property value changes
        /// </summary>
        public new event EventHandler TextChanged;

        /// <summary>
        /// Occurs when the control loses focus
        /// 
        /// </summary>
        public new event EventHandler LostFocus;

        /// <summary>
        /// Occurs when the <code>System.Windows.Forms.Control.Enabled</code> property value has changed
        /// </summary>
        public new event EventHandler EnabledChanged;
        #endregion

        #region Properties
        private FontStyle initFontStyle;
        /// <summary>
        /// Stores font-style used at initialization
        /// </summary>
        public FontStyle InitialFontStyle { get { return initFontStyle; } }

        private Cursor initCursor;
        /// <summary>
        /// Stores cursor used at initialization
        /// </summary>
        public Cursor InitialCursor { get { return initCursor; } }

        /// <summary>
        /// Stores the original text colour before modifications
        /// </summary>
        public Color InitialForeColor { get; private set; }

        /// <summary>
        /// Stores the original background colour before modifications
        /// </summary>
        public Color InitialBackColor { get; private set; }

        /// <summary>
        /// Watermark text
        /// </summary>
        public string WatermarkText { get; set; }

        /// <summary>
        /// Focuses automatically on mouse hover, if TRUE
        /// </summary>
        public bool FocusOnHover { get; set; }

        /// <summary>
        /// Specifies if link behaviour should be allowed
        /// </summary>
        public bool LinkBehaviour { get; set; }

        /// <summary>
        /// Colour when link behaviour is activated
        /// </summary>
        public Color LinkColour { get; set; }

        /// <summary>
        /// Specifies whether to supress the TextChanged event
        /// </summary>
        private bool SuppressTextChanged { get; set; }

        /// <summary>
        /// Colour when watermark is activated
        /// </summary>
        public Color WatermarkColour { get; set; }

        /// <summary>
        /// Backing field for WatermarkVisible
        /// </summary>
        private bool watermarkVisible;
        /// <summary>
        /// Determines whether the watermark should be visible
        /// </summary>
        public bool WatermarkVisible
        {
            get { return watermarkVisible; }
            set { watermarkVisible = value; }
        }

        /// <summary>
        /// Specifies if watermark is the text associated with the control
        /// </summary>
        public bool IsWatermarkText { get { return base.Text == WatermarkText; } }

        public bool IsLogicalBlank { get { return (base.Text.IsBlank() || this.IsWatermarkText); } }
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new default instance of <code>CommonUtilities.Controls.CUtil_TextBox</code>
        /// </summary>
        public CUtil_TextBox()
            : base()
        {
            // Default values of properties
            FocusOnHover = true;
            LinkBehaviour = true;
            LinkColour = Color.Blue;
            WatermarkVisible = true;
            WatermarkColour = Color.Gray;
            InitialForeColor = base.ForeColor; // Backup ForeColor
            InitialBackColor = base.BackColor = Color.NavajoWhite; // Assign BackColor for distinction
            Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));

            base.Text = WatermarkText;
            AssignWatermark(true);

            // Event assignment
            base.MouseEnter += new EventHandler(CUtil_TextBox_MouseEnter);
            base.MouseLeave += new EventHandler(CUtil_TextBox_MouseLeave);
            base.GotFocus += new EventHandler(CUtil_TextBox_GotFocus);
            base.TextChanged += new EventHandler(CUtil_TextBox_TextChanged);
            base.LostFocus += new EventHandler(CUtil_TextBox_LostFocus);
            base.EnabledChanged += new EventHandler(CUtil_TextBox_EnabledChanged);
        }

        /// <summary>
        /// Occurs when the <code>System.Windows.Forms.Control.Enabled</code> property value has changed
        /// </summary>
        void CUtil_TextBox_EnabledChanged(object sender, EventArgs e)
        {
            if (base.Enabled)
                base.BackColor = InitialBackColor; // Restore BackColor
            else
            {
                InitialBackColor = base.BackColor; // Backup BackColor
                base.BackColor = Color.MistyRose;
            }

            if (!this.EnabledChanged.IsNull())
                this.EnabledChanged(sender, e);
        }
        #endregion

        #region Formatting events
        /// <summary>
        /// Occurs when the mouse pointer enters the control
        /// </summary>
        private void CUtil_TextBox_MouseEnter(object sender, EventArgs e)
        {
            // InitialForeColor = base.ForeColor; // Backup ForeColor
            base.ForeColor = LinkColour;

            AssignWatermark(true);

            if (FocusOnHover) { base.Focus(); /* SendKeys.Send("{End}");*/ }

            // Back-up of initialized values
            this.initFontStyle = base.Font.Style;
            this.initCursor = base.Cursor;

            if (LinkBehaviour && Form.ModifierKeys == Keys.Control)
            {
                base.Font = new Font(base.Font.FontFamily, base.Font.Size, FontStyle.Underline, base.Font.Unit, base.Font.GdiCharSet);
                base.Cursor = Cursors.Hand;
            }

            if (!this.MouseEnter.IsNull())
                this.MouseEnter(sender, e);
        }

        /// <summary>
        /// Occurs when the mouse pointer leaves the control
        /// </summary>
        private void CUtil_TextBox_MouseLeave(object sender, EventArgs e)
        {
            base.ForeColor = InitialForeColor; // Restore ForeColor
            AssignWatermark(true);

            if (LinkBehaviour)
            {
                base.Font = new Font(base.Font.FontFamily, base.Font.Size, InitialFontStyle, base.Font.Unit, base.Font.GdiCharSet);
                base.Cursor = InitialCursor;
            }

            if (!this.MouseLeave.IsNull())
                this.MouseLeave(sender, e);
        }

        /// <summary>
        /// Occurs when the control receives focus
        /// </summary>
        private void CUtil_TextBox_GotFocus(object sender, EventArgs e)
        {
            // InitialForeColor = base.ForeColor; // Backup ForeColor
            if (WatermarkVisible)
            {
                SuppressTextChanged = true;
                if (IsWatermarkText) base.Text = "";
                base.ForeColor = InitialForeColor;
                SuppressTextChanged = false;
            }

            if (!this.GotFocus.IsNull())
                this.GotFocus(sender, e);
        }

        /// <summary>
        /// Occurs when the <code>System.Windows.Forms.Control.Text</code> property value changes
        /// </summary>
        private void CUtil_TextBox_TextChanged(object sender, EventArgs e)
        {
            if (!SuppressTextChanged)
            {
                if (WatermarkVisible)
                {
                    SuppressTextChanged = true;
                    if (!this.Focused && base.Text.IsBlank()) base.Text = WatermarkText;
                    base.ForeColor = IsWatermarkText ? WatermarkColour : InitialForeColor;
                    SuppressTextChanged = false;
                }
                else
                {
                    SuppressTextChanged = true;
                    base.ForeColor = InitialForeColor;
                    SuppressTextChanged = false;
                }
            }

            if (!this.TextChanged.IsNull())
                this.TextChanged(sender, e);
        }

        /// <summary>
        /// Occurs when the control loses focus
        /// </summary>
        private void CUtil_TextBox_LostFocus(object sender, EventArgs e)
        {
            if (WatermarkVisible)
            {
                SuppressTextChanged = true;
                if (base.Text.IsBlank()) base.Text = WatermarkText;
                base.ForeColor = (this.IsLogicalBlank) ? WatermarkColour : InitialForeColor;
                SuppressTextChanged = false;
            }

            if (!this.LostFocus.IsNull())
                this.LostFocus(sender, e);
        }
        #endregion

        #region Methods
        /// <summary>
        /// Assigns watermark to control
        /// </summary>
        /// <param name="displayWatermark">TRUE: Displays watermark</param>
        private void AssignWatermark(bool displayWatermark)
        {
            if (WatermarkVisible)
            {
                if (this.IsLogicalBlank && (displayWatermark && !this.Focused))
                {
                    SuppressTextChanged = true;
                    base.Text = displayWatermark ? WatermarkText : "";
                    base.ForeColor = displayWatermark ? WatermarkColour : InitialForeColor;
                    SuppressTextChanged = false;
                }
            }
        }

        /// <summary>
        /// Returns a string that represents the <code>CommonUtilities.Controls.CUtil_TextBox</code> control
        /// </summary>
        public override string ToString()
        {
            return Utilities.ToString(this);
        }
        #endregion
    }
}
